<?php
namespace Base;
require_once 'Zend/Session/Namespace.php';
class BaseOrmModel
{
    public static $charset = 'UTF8';
    public static $stmt = null;
    public static $connect = false; // 长链接是否开启
    private static $DB = null;
    private static $LOG_DB = null;

    public $table = '';

    CONST DB_CONFIG_FILE = "Env";
    private static $db_config_list;
    public $master_db = 'sdk_master';
    public $log_db = 'log_master';

    public function __construct()
    {
        try {
            if (self::$DB == null ||self::$LOG_DB == null ) {
                $this->getConnection();
            }
        } catch (\PDOException $e) {
            throw new \Base\Exception\MysqlErrorException("Connect Error Information:" . $e->getMessage());
        }
        self::$DB->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
        self::$DB->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
        self::execute('SET NAMES ' . self::$charset);


        self::$LOG_DB->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
        self::$LOG_DB->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
        self::execute_log('SET NAMES ' . self::$charset);
    }

    private function getConnection()
    {
        // 获取配置文件数据库配置
        $db_config_list = $this->getConfigList();
        //鲜用她  数据库配置信息
        $db_config = $db_config_list[$this->master_db];
        $port = isset($db_config['port']) ? $db_config['port'] : 3306;
        self::$DB = new \PDO($db_config['db_type'] . ':host=' . $db_config['host'] . ';port=' . $port . ';dbname=' . $db_config['db_name'], $db_config['db_user'], $db_config['db_password'], array(
            \PDO::ATTR_PERSISTENT => self::$connect,
            \PDO::ATTR_TIMEOUT => $db_config['timeout']
        ));

        //鲜用她  系统日志配置
        $log_config = $db_config_list[$this->log_db];
        $port_log = isset($log_config['port']) ? $log_config['port'] : 3306;
        self::$LOG_DB = new \PDO($log_config['db_type'] . ':host=' . $log_config['host'] . ';port=' . $port_log . ';dbname=' . $log_config['db_name'], $log_config['db_user'], $log_config['db_password'], array(
            \PDO::ATTR_PERSISTENT => self::$connect,
            \PDO::ATTR_TIMEOUT => $log_config['timeout']
        ));
    }

    public function disConnection()
    {
        self::$DB = null;
    }

    public function execute($sql)
    {
        $result = self::$DB->exec($sql);
        if (self::$DB->errorCode() != '00000') {
            $err_info = self::$DB->errorInfo();
            throw new \Base\Exception\MysqlErrorException("SQL error: $sql" . '. Error info: ' . isset($err_info[2]) ? $err_info[2] : '');
        }
        return $result;
    }

    public function execute_log($sql)
    {
        $result = self::$LOG_DB->exec($sql);
        if (self::$LOG_DB->errorCode() != '00000') {
            $err_info = self::$LOG_DB->errorInfo();
            throw new \Base\Exception\MysqlErrorException("SQL error: $sql" . '. Error info: ' . isset($err_info[2]) ? $err_info[2] : '');
        }
        return $result;
    }

    public function getLastId()
    {
        return self::$DB->lastInsertId();
    }

    public function loadById($id)
    {
        $id = (int) $id;
        $result = $this->fetchOne('*', "`id`={$id} AND `is_del` = 0");
        if ($result) {
            return $result;
        }
//        debug_print_backtrace();exit;
        throw new \Base\Exception\NoRecordException("{$this->table} No record find by id [{$id}]");
    }

    public function loadByIdWithDel($id)
    {
        $id = (int) $id;
        $result = $this->fetchOne('*', "`id`={$id}");
        if ($result) {
            return $result;
        }
        throw new \Base\Exception\NoRecordException("No record find by id [{$id}]");
    }
    public function getMaxId()
    {
        $result = $this->fetchOne('max(id) as id');
        if ($result) {
            return $result['id'];
        } else {
            return 0;
        }
    }

    public function insert($args)
    {
        if (empty($args)) {
            return false;
        }
        $sql = "INSERT INTO `$this->table` SET ";
        $code = self::_getCode($args);
        $sql .= $code;
        $result = self::execute($sql);
        if (self::$DB->errorCode() != '00000') {
            $err_info = self::$DB->errorInfo();
            throw new \Base\Exception\MysqlErrorException("SQL error: $sql" . '. Error info: ' . isset($err_info[2]) ? $err_info[2] : '');
        }
        return $result;
    }

    /**
     * 批量插入
     * @param $table
     * @param array $data
     * @return bool|int
     */
    public function insertList($table, array $data) {
        if (empty($data)) {
            return false;
        }
        $cols = '';
        $values = '';
        foreach ($data[0] as $k => $v) {
            $cols = $cols.'`'.$k.'`'.',';
        }
        foreach ($data as $k => $row) {
            $row = '("'.implode($row, '","').'")';
            $values = $values.$row.',';
        }
        $cols = rtrim($cols,',');
        $values = rtrim($values,',');
        $sql = "INSERT INTO `$table` ($cols) VALUES $values";
        return self::execute($sql);
    }

    public function insertMulti($args)
    {
        if (empty($args)) {
            return false;
        }
        $sql = "INSERT INTO `$this->table` SET ";
        $code_arr = array();
        foreach ($args as $arg) {
            if (!is_array($arg)) {
                return false;
            }
            $code = self::_getCode($arg);
            $code_arr[] = '(' . $code . ')';
        }
        $code_str = implode(',', $code_arr);
        $sql .= $code_str;
        $result = self::execute($sql);
        if (self::$DB->errorCode() != '00000') {
            $err_info = self::$DB->errorInfo();
            throw new \Base\Exception\MysqlErrorException("SQL error: $sql" . '. Error info: ' . isset($err_info[2]) ? $err_info[2] : '');
        }
        return $result;
    }

    private function _getCode($args)
    {
        $code = '';
        if (is_array($args)) {
            foreach ($args as $k => $v) {
                $code .= "`$k`='$v',";
            }
        }
        $code = substr($code, 0, -1);
        return $code;
    }

    public function update($args, $where)
    {
        if (empty($where)) {
            return false;
        }
        $code = self::_getCode($args);
        $sql = "UPDATE `$this->table` SET ";
        $sql .= $code;
        $sql .= " WHERE $where";

        $result = self::execute($sql);
        if (self::$DB->errorCode() != '00000') {
            $err_info = self::$DB->errorInfo();
            throw new \Base\Exception\MysqlErrorException("SQL error: $sql" . '. Error info: ' . isset($err_info[2]) ? $err_info[2] : '');
        }
        return $result !== false;
    }

    public function delete($where)
    {
        if (empty($where)) return false;
        $sql = "DELETE FROM `$this->table` Where $where";
        return self::execute($sql);
    }

    public function fetchOne($field = '*', $where = false)
    {
        $sql = "SELECT {$field} FROM `{$this->table}`";
        $sql .= $where ? " WHERE $where" : '';
        //echo $sql;
        return self::_fetch($sql, $type = '0');
    }

    public function _fetch($sql, $type)
    {
        $result = array();
        self::$stmt = self::$DB->query($sql);
        if (self::$stmt == false) {
            $err_info = self::$DB->errorInfo();
            throw new \Base\Exception\MysqlErrorException("SQL error: $sql" . '. Error info: ' . isset($err_info[2]) ? $err_info[2] : '');
        }

        self::$stmt->setFetchMode(\PDO::FETCH_ASSOC);
        switch ($type) {
            case '0':
                $result = self::$stmt->fetch();
                break;
            case '1':
                $result = self::$stmt->fetchAll();
                break;
            case '2':
                $result = self::$stmt->rowCount();
                break;
        }
        self::$stmt = null;
        return $result;
    }

    public function fetchAll($field = '*', $orderby = false, $where = false, $limit = false, $offset = 0)
    {
        $sql = "SELECT {$field} FROM `{$this->table}`";
        $sql .= $where ? " WHERE $where" : '';
        $sql .= $orderby ? " ORDER BY $orderby" : '';
        $sql .= $limit ? " LIMIT  $offset, $limit" : '';

        return self::_fetch($sql, $type = '1');
    }

    public function fetchRowCount($field = '*', $where = false)
    {
        $sql = "SELECT COUNT({$field}) AS num FROM $this->table";
        $sql .= $where ? " WHERE $where" : '';
        
        return self::_fetch($sql, $type = '0');
    }

    public function beginTransaction()
    {
        return self::$DB->beginTransaction();
    }

    public function commit()
    {
        return self::$DB->commit();

    }

    public function rollBack()
    {
        return self::$DB->rollBack();
    }

    private function getConfigList()
    {
        if (empty(self::$db_config_list)) {
            self::$db_config_list = \Util\Config::get("db", self::DB_CONFIG_FILE);
        }
        return self::$db_config_list;
    }


    /**
     * for log data
     * @param string $ref_key
     * @param string $memo
     * @param array $data
     */
    public function log($ref_key='', $memo='', $data=array())
    {
        try {
            if(count($data) == 0) { $data = $this->fetchOne('*', "`id`={$ref_key}");}
            if($data && $ref_key)
            {
                $tmp_table_name = substr($this->table,1);
                $log_table_name = "`blog{$tmp_table_name}`";
                $user_session = new \Zend_Session_Namespace('login');
                $customer_session = new \Zend_Session_Namespace('user');
                if (isset($user_session->user_id) &&  $user_session->user_id != '') {
                    $staff_id = $user_session->user_id;
                } else if(isset($customer_session->customer_id) &&  $customer_session->customer_id != '') {
                    $staff_id = $customer_session->customer_id;
                }else{
                    $staff_id = 0;
                }
                $log_json = addslashes(json_encode($data));
                $create_ip = $this->ipAddr();
                $sql = "INSERT INTO {$log_table_name} (`fk_staff_id`,`fk_ref_key`,`log_memo`,`log_json`,`create_ip`)
                     VALUES ({$staff_id},{$ref_key},'{$memo}','{$log_json}',{$create_ip})";
                self::execute_log($sql);
            }
        }catch (\Exception $e){

        }
    }

    /**
     * 显示所有列
     * @param $table_name
     * @return array
     */
    public function getColumnsInfo($table_name)
    {
        $sql = "show full columns from {$table_name};";
        $result = $this->_fetch($sql, 1);
        return $result;
    }
    public function ipAddr()
    {
        $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] :'127.0.0.1';
        return ip2long($ip);
    }
}